Skip to content

[9.0] [FSH] @kbn/fs package (#243037)#243978

Closed
elena-shostak wants to merge 1 commit into
elastic:9.0from
elena-shostak:backport/9.0/pr-243037
Closed

[9.0] [FSH] @kbn/fs package (#243037)#243978
elena-shostak wants to merge 1 commit into
elastic:9.0from
elena-shostak:backport/9.0/pr-243037

Conversation

@elena-shostak
Copy link
Copy Markdown
Contributor

Backport

This will backport the following commits from main to 9.0:

Questions ?

Please refer to the Backport tool documentation

## Summary

Introduced the `@kbn/fs` package that wraps node `fs` API with safe
defaults:

- every write resolves paths under the repo `data` root folder
- validates that there is no path traversal
- validates allowed file extensions
- validates allowed mime types
- validates allowed file sizes
- performs sanitization for svg

Introduced eslint rule `@kbn/eslint/require_kbn_fs` that flags the
direct write `fs` calls in production code. Severity is set to `warn`
for now and will be switched to `error` once migration is done in scope
of elastic#239385.

Exposed interface has a `volume` that serves as logical namespace. You
select a volume (e.g., `reports`, `exports/run-123`) and pass a file
name, `getSafePath` constructs a full path under `data/volume/...`. That
allows us to introduce per-volume restrictions later (file size, mime
types, etc) if needed and extend the interface without friction.

## How to test
You can add a test route to check that out easily.
<details>
  <summary>POST /internal/security/files</summary>

```ts
  export function defineFileRoutes({ router }: RouteDefinitionParams) {
    router.post(
      {
        path: '/internal/security/files',
        security: {
          authz: {
            enabled: false,
            reason: 'Test route for file operations',
          },
        },
        validate: {
          request: {
            body: schema.object({
              method: schema.string(),
              name: schema.string(),
              content: schema.string(),
              volume: schema.maybe(schema.string()),
            }),
          },
        },
      },
      createLicensedRouteHandler(async (context, request, response) => {
        const { method, name, content, volume = 'security-test' } = request.body;

        try {
          switch (method) {
            case 'writeFile':
              const resultWriteFile = await writeFile(name, content, {
                volume,
              });

              return response.ok({ body: resultWriteFile });
            case 'appendFile':
              const resultAppendFile = await appendFile(name, content, {
                volume,
              });

              return response.ok({ body: resultAppendFile });
            case 'writeFileSync':
              const resultWriteFileSync = writeFileSync(name, content, {
                volume,
              });
              return response.ok({ body: resultWriteFileSync });
            case 'appendFileSync':
              const resultAppendFileSync = appendFileSync(name, content, {
                volume,
              });
              return response.ok({ body: resultAppendFileSync });

            case 'createWriteStream':
              const writeStream = createWriteStream(name, volume);
              writeStream.write(content);
              writeStream.end();
              return response.ok({ body: 'ok' });

            case 'readFile':
              const fileContent = await readFile(name, volume);
              return response.ok({ body: fileContent });

            default:
              return response.customError(wrapIntoCustomErrorResponse(new Error('Invalid method')));
          }
        } catch (error) {
          return response.customError(wrapIntoCustomErrorResponse(error));
        }
      })
    );
  }
```
</details>

### Checklist
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [x] The PR description includes the appropriate Release Notes section,
and the correct `release_note:*` label is applied per the
[guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)
- [x] Review the [backport
guidelines](https://docs.google.com/document/d/1VyN5k91e5OVumlc0Gb9RPa3h1ewuPE705nRtioPiTvY/edit?usp=sharing)
and apply applicable `backport:*` labels.

__Closes: https://github.com/elastic/kibana/issues/239382__

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
(cherry picked from commit 20efb62)

# Conflicts:
#	.buildkite/scripts/steps/security/third_party_packages.txt
#	.eslintrc.js
#	.github/CODEOWNERS
#	package.json
#	src/dev/license_checker/config.ts
#	tsconfig.base.json
#	yarn.lock
@elena-shostak elena-shostak added the backport This PR is a backport of another PR label Nov 24, 2025
@elena-shostak elena-shostak enabled auto-merge (squash) November 24, 2025 13:02
@elasticmachine
Copy link
Copy Markdown
Contributor

CI was triggered for this PR, but this PR targets 9.0 which should not receive a future release. CI is not supported for these branches. Please consult the release schedule, or contact #kibana-operations if you believe this is an error.

The following branches are currently considered to be open:

  • main
  • 9.2
  • 9.1
  • 8.19
  • 7.17

1 similar comment
@elasticmachine
Copy link
Copy Markdown
Contributor

CI was triggered for this PR, but this PR targets 9.0 which should not receive a future release. CI is not supported for these branches. Please consult the release schedule, or contact #kibana-operations if you believe this is an error.

The following branches are currently considered to be open:

  • main
  • 9.2
  • 9.1
  • 8.19
  • 7.17

@elena-shostak elena-shostak mentioned this pull request Nov 24, 2025
3 tasks
auto-merge was automatically disabled November 24, 2025 14:26

Pull request was closed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backport This PR is a backport of another PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants